// Copyright 2011, Vanya Davidenko.
// Кодировка файла: UTF-8. 
package info.iu9.red;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;


public class RegexTest {
  @Before
  public void setUp() {}

  @After
  public void tearDown() {}


  @Test
  public void utf16SurrogateTest() {
    newRegex("((\uD834\uDD1E)|u|\u6C34)+");
    assertTrue(regex_.matches("\uD834\uDD1Eu\u6C34"));
  }

  @Test
  public void utf16LongString() {
    newRegex("((\uD834\uDD1E))+");
    assertTrue(regex_.matches("\uD834\uDD1E\uD834\uDD1E\uD834\uDD1E"));
  }

  @Test
  public void aLotOfAnchorsTest() {
    newRegex("\\b^\\b\\Aa\\b\n(?m:^\\bb\\Ba\\b$)\n$\\B\\Z\n\\B\\z\\B");
    assertTrue(regex_.matches("a\nba\n\n"));
  }


  @Test
  public void empty() {
    newRegex("");
    assertTrue(regex_.matches(""));
    assertFalse(regex_.matches("a"));
  }

  @Test
  public void oneLetter() {
    newRegex("a");
    assertTrue(regex_.matches("a"));
    assertFalse(regex_.matches("b"));
  }

  @Test
  public void string() {
    newRegex("regex test\n");
    assertTrue(regex_.matches("regex test\n"));
    assertFalse(regex_.matches("test regex\n"));
  }


  @Test(expected=RegexException.class)
  public void alternativeErrorLeftIsEmpty() {
    newRegex("|bcd");
  }

  @Test(expected=RegexException.class)
  public void alternativeErrorRightIsEmpty() {
    newRegex("a|");
  }

  @Test(expected=RegexException.class)
  public void alternativeErrorMiddleIsEmpty() {
    newRegex("a||c");
  }

  @Test
  public void alternativeSimple() {
    newRegex("a|b");
    assertTrue(regex_.matches("a"));
    assertTrue(regex_.matches("b"));
    assertFalse(regex_.matches("c"));
  }

  @Test
  public void alternative() {
    newRegex("a|bcd|^$");
    assertTrue(regex_.matches("a"));
    assertTrue(regex_.matches("bcd"));
    assertTrue(regex_.matches(""));
    assertFalse(regex_.matches("ab"));
    assertFalse(regex_.matches("abcd"));
  }

  @Test
  public void concatenationEmpty() {
    newRegex("");
    assertTrue(regex_.matches(""));
    assertFalse(regex_.matches("a"));
  }

  @Test
  public void concatenationOneCharacter() {
    newRegex("a");
    assertTrue(regex_.matches("a"));
    assertFalse(regex_.matches(""));
    assertFalse(regex_.matches("ab"));
  }

  @Test
  public void concatenationManyCharacters() {
    newRegex("abc");
    assertTrue(regex_.matches("abc"));
    assertFalse(regex_.matches("ab"));
    assertFalse(regex_.matches("abcd"));
  }


  @Test
  public void anchoringBeginSingleLineSimple() {
    newRegex(".*^a.*");
    assertTrue(regex_.matches("a"));
    assertFalse(regex_.matches("ba"));

    newRegex("a^a");
    assertFalse(regex_.matches("a"));
    assertFalse(regex_.matches("aa"));
  }

  @Test
  public void anchoringBeginSingleLineIsNotMultiline() {
    newRegex("\n^a");
    assertFalse(regex_.matches("\na"));
    assertFalse(regex_.matches("a"));
  }

  @Test
  public void anchoringBeginSingleLine() {
    newRegex("(?ns:.*^a.*)");
    assertTrue(regex_.matches("a"));
    assertFalse(regex_.matches("ba"));
    assertFalse(regex_.matches("\na"));
  }

  @Test
  public void anchoringBeginMultiLine() {
    newRegex("(?mns:.*^a.*)");
    assertTrue(regex_.matches("a"));
    assertTrue(regex_.matches("\na"));
    assertTrue(regex_.matches("\n\na"));
    assertFalse(regex_.matches("ba"));
    assertFalse(regex_.matches("\n a"));
  }

  @Test
  public void anchoringEndSingleLineSimple() {
    newRegex("a$.*");
    assertTrue(regex_.matches("a"));
    assertFalse(regex_.matches("ab"));

    newRegex("a$\n");
    assertTrue(regex_.matches("a\n"));
  }

  @Test
  public void anchoringEndSingleLine() {
    newRegex("(?ns:a$.*)");
    assertTrue(regex_.matches("a"));
    assertTrue(regex_.matches("a\n"));

    assertFalse(regex_.matches("ab"));
    assertFalse(regex_.matches("a\nb"));
    assertFalse(regex_.matches("a\n\n"));
  }

  @Test
  public void anchoringEndMultiLine() {
    newRegex("(?nms:a$.*)");
    assertTrue(regex_.matches("a"));
    assertTrue(regex_.matches("a\n"));
    assertTrue(regex_.matches("a\n\n"));
    assertTrue(regex_.matches("a\nb"));

    assertFalse(regex_.matches("ab"));
  }

  @Test
  public void anchoringSingleLineComplex() {
    newRegex("^^a$$\n*");
    assertTrue(regex_.matches("a"));
    assertTrue(regex_.matches("a\n"));

    assertFalse(regex_.matches("\na"));
    assertFalse(regex_.matches("a\n\n"));

    newRegex("^$^$");
    assertTrue(regex_.matches(""));
    assertFalse(regex_.matches("\n"));
  }

  @Test
  public void anchoringMultiLineComplex() {
    newRegex("(?mns:.*^^a$$.*)");
    assertTrue(regex_.matches("a"));
    assertTrue(regex_.matches("\na"));
    assertTrue(regex_.matches("a\n"));
    assertTrue(regex_.matches("\n\na\n\n"));
    assertFalse(regex_.matches("ba"));
    assertFalse(regex_.matches("ab"));

    newRegex("^$^$");
    assertTrue(regex_.matches(""));
    assertFalse(regex_.matches("\n"));
  }

  @Test
  public void anchoringAreSpecialCharacters() {
    newRegex("^");
    assertFalse(regex_.matches("^"));

    newRegex("$");
    assertFalse(regex_.matches("$"));
  }

  // ... //


  private void newRegex(final String pattern) {
    regex_ = new Regex(pattern);
  }

  private Regex regex_;
}
